/** 
 * ================================================================================
 * 		Project		: Kompas Bola
 * 		File		: PullRefresh.java
 * 		Description	: UI Pull to refresh
 * 		Called		: MainActivity.java
 * ================================================================================
 * */
package com.kompas.bola.application.ui;

import com.kompas.bola.application.R;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.webkit.WebView;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.AbsListView.OnScrollListener;

public class ListUI extends ListView implements OnScrollListener{

    private static final int TAP_TO_REFRESH 			= 1;
    private static final int PULL_TO_REFRESH 			= 2;
    private static final int RELEASE_TO_REFRESH 		= 3;
    private static final int REFRESHING 				= 4;
    
    private LayoutInflater mInflater;
    private OnScrollListener mOnScrollListener;
    private OnRefreshListener mOnRefreshListener;

    private TextView mRefreshViewText;
    private RelativeLayout mRefreshView;
	private RelativeLayout mFooterView;
    private ImageView mRefreshViewImage;
    private ProgressBar mRefreshViewProgress;
    private TextView mRefreshViewLastUpdated;

    private int mRefreshState;
    private int mCurrentScrollState;

    private RotateAnimation mFlipAnimation;
    private RotateAnimation mReverseFlipAnimation;

    private int mLastMotionY;
    private int mRefreshViewHeight;
    private int mRefreshOriginalTopPadding;

    private boolean mBounceHack;

    /** 
     * LOAD MORE */
	private boolean mIsLoadingMore = false;
	private ProgressBar mProgressBarLoadMore;
	private TextView loading;
	private OnLoadMoreListener mOnLoadMoreListener;
	/** =========================================================================== */
	public ListUI(Context context) {
		super(context);
        init(context);
	}
	/** =========================================================================== */
	public ListUI(Context context, AttributeSet attrs){
        super(context, attrs);
        init(context);		
	}
	/** =========================================================================== */
	public ListUI(Context context, AttributeSet attrs, int defStyle){
        super(context, attrs, defStyle);
        init(context);		
	}
	/** =========================================================================== */
	private void init(Context context) {
        mFlipAnimation 									= new RotateAnimation(0, -180,
													    RotateAnimation.RELATIVE_TO_SELF, 0.5f,
													    RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        mFlipAnimation.setInterpolator(new LinearInterpolator());
        mFlipAnimation.setDuration(250);
        mFlipAnimation.setFillAfter(true);
        mReverseFlipAnimation 							= new RotateAnimation(-180, 0,
													    RotateAnimation.RELATIVE_TO_SELF, 0.5f,
													    RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        
        mReverseFlipAnimation.setInterpolator(new LinearInterpolator());
        mReverseFlipAnimation.setDuration(250);
        mReverseFlipAnimation.setFillAfter(true);

        mInflater 										= (LayoutInflater) context.getSystemService(
               											Context.LAYOUT_INFLATER_SERVICE);

		mRefreshView 									= (RelativeLayout) mInflater.inflate(
														R.layout.pull_to_refresh_header, this, false);
        
		mRefreshViewText 								= (TextView) mRefreshView.findViewById(R.id.pull_to_refresh_text);
        mRefreshViewImage 								= (ImageView) mRefreshView.findViewById(R.id.pull_to_refresh_image);
        mRefreshViewProgress 							= (ProgressBar) mRefreshView.findViewById(R.id.pull_to_refresh_progress);
        mRefreshViewLastUpdated 						= (TextView) mRefreshView.findViewById(R.id.pull_to_refresh_updated_at);

        mRefreshViewImage.setMinimumHeight(50);
        mRefreshView.setOnClickListener(new OnClickRefreshListener());
        mRefreshOriginalTopPadding 						= mRefreshView.getPaddingTop();
        mRefreshState 									= TAP_TO_REFRESH;

        /** 
         * LOAD MORE */
		mFooterView 									= (RelativeLayout) mInflater.inflate(R.layout.load_more_footer, this, false);
		mProgressBarLoadMore 							= (ProgressBar) mFooterView.findViewById(R.id.load_more_progressBar);
		loading				 							= (TextView) mFooterView.findViewById(R.id.loading);
       
        addHeaderView(mRefreshView);
		addFooterView(mFooterView);
				
        super.setOnScrollListener(this);
        measureView(mRefreshView);
        mRefreshViewHeight 								= mRefreshView.getMeasuredHeight();
    }
	/** =========================================================================== */
    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        setSelection(1);
    }
	/** =========================================================================== */
    @Override
    public void setAdapter(ListAdapter adapter) {
        super.setAdapter(adapter);
        setSelection(1);
    }
	/** =========================================================================== */
    @Override
    public void setOnScrollListener(AbsListView.OnScrollListener l) {
        mOnScrollListener = l;
    }
	/** =========================================================================== */
    public void setOnRefreshListener(OnRefreshListener onRefreshListener) {
        mOnRefreshListener = onRefreshListener;
    }
	/** =========================================================================== */
	public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
		mOnLoadMoreListener = onLoadMoreListener;
	}
	/** =========================================================================== */
    public void setLastUpdated(CharSequence lastUpdated) {
        if (lastUpdated != null) {
            mRefreshViewLastUpdated.setVisibility(View.VISIBLE);
            mRefreshViewLastUpdated.setText(lastUpdated);
        } else {
            mRefreshViewLastUpdated.setVisibility(View.GONE);
        }
    }
	/** =========================================================================== */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        final int y = (int) event.getY();
        mBounceHack = false;

        switch (event.getAction()) {
            case MotionEvent.ACTION_UP:
                if (!isVerticalScrollBarEnabled()) {
                    setVerticalScrollBarEnabled(true);
                }
                if (getFirstVisiblePosition() == 0 && mRefreshState != REFRESHING) {
                    if ((mRefreshView.getBottom() >= mRefreshViewHeight
                            || mRefreshView.getTop() >= 0)
                            && mRefreshState == RELEASE_TO_REFRESH) {
                        // Initiate the refresh
                        mRefreshState = REFRESHING;
                        prepareForRefresh();
                        onRefresh();
                    } else if (mRefreshView.getBottom() < mRefreshViewHeight
                            || mRefreshView.getTop() <= 0) {
                        // Abort refresh and scroll down below the refresh view
                        resetHeader();
                        setSelection(1);
                    }
                }
                break;
            case MotionEvent.ACTION_DOWN:
                mLastMotionY = y;
                break;
            case MotionEvent.ACTION_MOVE:
                applyHeaderPadding(event);
                break;
        }
        return super.onTouchEvent(event);
    }
	/** =========================================================================== */
    public void applyHeaderPadding(MotionEvent ev) {
        int pointerCount = ev.getHistorySize();

        for (int p = 0; p < pointerCount; p++) {
            if (mRefreshState == RELEASE_TO_REFRESH) {
                if (isVerticalFadingEdgeEnabled()) {
                    setVerticalScrollBarEnabled(false);
                }

                int historicalY = (int) ev.getHistoricalY(p);
                int topPadding = (int) (((historicalY - mLastMotionY)
                        - mRefreshViewHeight) / 1.7);

                mRefreshView.setPadding(
                        mRefreshView.getPaddingLeft(),
                        topPadding,
                        mRefreshView.getPaddingRight(),
                        mRefreshView.getPaddingBottom());
            }
        }
    }
	/** =========================================================================== */
    public void resetHeaderPadding() {
        mRefreshView.setPadding(
                mRefreshView.getPaddingLeft(),
                mRefreshOriginalTopPadding,
                mRefreshView.getPaddingRight(),
                mRefreshView.getPaddingBottom());
    }
	/** =========================================================================== */
    public void resetHeader() {
        if (mRefreshState != TAP_TO_REFRESH) {
            mRefreshState = TAP_TO_REFRESH;

            resetHeaderPadding();
  
            mRefreshViewProgress.setVisibility(View.VISIBLE);
            mRefreshViewText.setVisibility(View.VISIBLE);
            mRefreshViewText.setText(R.string.pull_to_refresh_tap_label);
            mRefreshViewImage.setImageResource(R.drawable.ic_pulltorefresh_arrow);
            mRefreshViewImage.clearAnimation();
            mRefreshViewImage.setVisibility(View.GONE);
            mRefreshViewProgress.setVisibility(View.GONE);
        }
    }
	/** =========================================================================== */
    public void measureView(View child) {
        ViewGroup.LayoutParams p 						= child.getLayoutParams();
        if (p == null) {
            p = new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.FILL_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);
        }

        int childWidthSpec 								= ViewGroup.getChildMeasureSpec(0,0 + 0, p.width);
        int lpHeight 									= p.height;
        int childHeightSpec;
        if (lpHeight > 0) {
            childHeightSpec 							= MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
        } else {
            childHeightSpec 							= MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        }
        child.measure(childWidthSpec, childHeightSpec);
    }
	/** =========================================================================== */
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
        if (mCurrentScrollState == SCROLL_STATE_TOUCH_SCROLL
                && mRefreshState != REFRESHING) {
            if (firstVisibleItem == 0) {
                mRefreshViewImage.setVisibility(View.VISIBLE);
                if ((mRefreshView.getBottom() >= mRefreshViewHeight + 20
                        || mRefreshView.getTop() >= 0)
                        && mRefreshState != RELEASE_TO_REFRESH) {
                    mRefreshViewText.setText(R.string.pull_to_refresh_release_label);
                    mRefreshViewImage.clearAnimation();
                    mRefreshViewImage.startAnimation(mFlipAnimation);
                    mRefreshState = RELEASE_TO_REFRESH;
                } else if (mRefreshView.getBottom() < mRefreshViewHeight + 20
                        && mRefreshState != PULL_TO_REFRESH) {
                    mRefreshViewText.setText(R.string.pull_to_refresh_pull_label);
                    if (mRefreshState != TAP_TO_REFRESH) {
                        mRefreshViewImage.clearAnimation();
                        mRefreshViewImage.startAnimation(mReverseFlipAnimation);
                    }
                    mRefreshState = PULL_TO_REFRESH;
                } 
            } else {
                mRefreshViewImage.setVisibility(View.GONE);
                resetHeader();
            }
        } else if (mCurrentScrollState == SCROLL_STATE_FLING
                && firstVisibleItem == 0
                && mRefreshState != REFRESHING) {
            setSelection(1);
            mBounceHack = true;
        } else if (mBounceHack && mCurrentScrollState == SCROLL_STATE_FLING) {
            setSelection(1);
        }

        if (mOnScrollListener != null) {
            mOnScrollListener.onScroll(view, firstVisibleItem,
                    visibleItemCount, totalItemCount);
        }
        
        /** 
         * LOAD MORE */

		if (mOnLoadMoreListener != null) {

			if (visibleItemCount == totalItemCount) {
				mProgressBarLoadMore.setVisibility(View.GONE);
				loading.setVisibility(View.GONE);
				// mLabLoadMore.setVisibility(View.GONE);
				return;
			}

			boolean loadMore = firstVisibleItem + visibleItemCount >= totalItemCount;

			if (!mIsLoadingMore && loadMore
					&& mCurrentScrollState != SCROLL_STATE_IDLE) {
				mProgressBarLoadMore.setVisibility(View.VISIBLE);
				loading.setVisibility(View.VISIBLE);
				// mLabLoadMore.setVisibility(View.VISIBLE);
				mIsLoadingMore = true;
				onLoadMore();
			}
			
			
			/*ads.loadData(Constants.ADS, "text/html", "UTF-8");
			ads.setVisibility(View.VISIBLE);*/

		}
    }
	/** =========================================================================== */
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        mCurrentScrollState = scrollState;

        if (mCurrentScrollState == SCROLL_STATE_IDLE) {
            mBounceHack = false;
        }

        if (mOnScrollListener != null) {
            mOnScrollListener.onScrollStateChanged(view, scrollState);
        }
    }
	/** =========================================================================== */
    public void prepareForRefresh() {
        resetHeaderPadding();

        mRefreshViewImage.setVisibility(View.GONE);
        mRefreshViewImage.setImageDrawable(null);
        mRefreshViewProgress.setVisibility(View.VISIBLE);
        mRefreshViewText.setVisibility(View.VISIBLE);
        mRefreshViewText.setText(R.string.pull_to_refresh_refreshing_label);

        mRefreshState = REFRESHING;
    }
	/** =========================================================================== */
    public void onRefresh() {
        if (mOnRefreshListener != null) {
            mOnRefreshListener.onRefresh();
        }
    }
	/** =========================================================================== */
	public void onLoadMore() {
		if (mOnLoadMoreListener != null) {
			mOnLoadMoreListener.onLoadMore();
			
			/*ads.loadData(Constants.ADS, "text/html", "UTF-8");
			ads.setVisibility(View.VISIBLE);*/
		}
	}
	/** =========================================================================== */
    public void onRefreshComplete(CharSequence lastUpdated) {
    	setLastUpdated(lastUpdated);
        onRefreshComplete();
    }
	/** =========================================================================== */
	public void onLoadMoreComplete() {
		mIsLoadingMore = false;
		mProgressBarLoadMore.setVisibility(View.GONE);
		loading.setVisibility(View.GONE);
	}
	/** =========================================================================== */
    public void onRefreshComplete() {        
        resetHeader();
        if (mRefreshView.getBottom() > 0) {
            invalidateViews();
            setSelection(1);
        }
    }
	/** =========================================================================== */
    public class OnClickRefreshListener implements OnClickListener {

        @Override
        public void onClick(View v) {
            if (mRefreshState != REFRESHING) {
                prepareForRefresh();
                onRefresh();
            }
        }
    }
	/** =========================CALL FUNCTION REFRESH============================= */
	public interface OnRefreshListener {
        public void onRefresh();		
	}
	/** =========================CALL FUNCTION LOADMORE============================ */
	public interface OnLoadMoreListener {
		public void onLoadMore();
	}
	/** =========================================================================== */
}
